package com.ruoyi.business.service.impl;

import com.ruoyi.business.service.IProcessService;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipInputStream;

@Service
public class ProcessServiceImpl implements IProcessService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;

    @Override
    public Deployment deploy(String filePath) throws IOException {
        //bpmn 或 zip
        Deployment deployment = null;
        if (filePath.endsWith("zip")) {
            ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(filePath));
            deployment = repositoryService.createDeployment()
                    .addZipInputStream(zipInputStream)
                    .deploy();
        } else if (filePath.endsWith("bpmn")) {
            deployment = repositoryService
                    .createDeployment()
                    .addInputStream(filePath, new FileInputStream(filePath))
                    .deploy();
        }
        return deployment;
    }

    @Override
    public ProcessDefinition selectProcessDefinitionByDeploymentId(String deploymentId) {
        return repositoryService
                .createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
    }

    @Override
    public InputStream getResourceAsStream(String deploymentId, String resourceName) {
        return repositoryService.getResourceAsStream(deploymentId, resourceName);
    }

    @Override
    public InputStream getProcessImage(String processDefinitionId, List<String> highLightActivities, List<String> highLightedFlows) {
        //根据流程定义id获取bpmn模型
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        //定义绘制图形对象
        DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        //1.BpmnModel 2.需要高亮的节点集合 3.需要高亮连线集合
        InputStream inputStream = generator.generateDiagram(bpmnModel, highLightActivities, highLightedFlows,
                "宋体", "宋体", "宋体");
        return inputStream;
    }

    @Override
    public ProcessInstance startProcessInstance(String definitionKey, String businessKey, HashMap<String, Object> variables) {
        return runtimeService.startProcessInstanceByKey(definitionKey, businessKey, variables);
    }

    @Override
    public Task getTaskByProcessInstanceId(String instanceId) {
        return taskService
                .createTaskQuery()
                .processInstanceId(instanceId)
                .singleResult();
    }

    @Override
    public void addCandidateUser(Task currentTask, Long userId) {
        taskService.addCandidateUser(currentTask.getId(), userId.toString());
    }

    @Override
    public List<String> getActiveActivityIds(String instanceId) {
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(instanceId);
        return activeActivityIds;
    }

    @Override
    public ProcessInstance getProcessInstanceById(String instanceId) {
        return runtimeService
                .createProcessInstanceQuery()
                .processInstanceId(instanceId)
                .singleResult();
    }

    @Override
    public void deleteProcessInstance(String instanceId, String reason) {
        runtimeService.deleteProcessInstance(instanceId, reason);
    }

    @Override
    public long selectTodoTaskCount(String definitionKey, String candidateUser) {
        return taskService
                .createTaskQuery()
                .processDefinitionKey(definitionKey)
                .taskCandidateUser(candidateUser)
                .count();
    }

    @Override
    public List<Task> selectTodoTaskList(String definitionKey, String candidateUser, Integer startNum, Integer pageSize) {
        return taskService
                .createTaskQuery()
                .processDefinitionKey(definitionKey)
                .taskCandidateUser(candidateUser)
                .orderByTaskCreateTime()
                .desc()
                .listPage(startNum, pageSize);
    }

    @Override
    public Task getTaskByTaskId(String taskId) {
        return taskService
                .createTaskQuery()
                .taskId(taskId)
                .singleResult();
    }

    @Override
    public void claimAndCompleteTask(Task task, String userId, Boolean auditStatus, String commentStr) {
        //添加批注
        taskService.addComment(task.getId(), task.getProcessInstanceId(), commentStr);
        //领取任务
        taskService.claim(task.getId(), userId);
        //设置流程变量 第一次设置直接加入流程变量中，第二次key相同，把流程变量覆盖
        taskService.setVariable(task.getId(), task.getTaskDefinitionKey(), auditStatus);
        //完成任务
        taskService.complete(task.getId());
    }

    @Override
    public void setVariable(String taskId, String variableName, long variableValue) {
        taskService.setVariable(taskId, variableName, variableValue);
    }

    @Override
    public long selectDoneTaskCount(String definitionKey, String userId) {
        return historyService
                .createHistoricTaskInstanceQuery()
                .processDefinitionKey(definitionKey)
                .taskAssignee(userId)
                .finished()
                .count();
    }

    @Override
    public List<HistoricTaskInstance> selectDoneTaskList(String definitionKey, String userId, Integer firstResult, Integer pageSize) {
        return historyService
                .createHistoricTaskInstanceQuery()
                .processDefinitionKey(definitionKey)
                .taskAssignee(userId)
                .finished()
                .orderByHistoricTaskInstanceEndTime()//必须加 desc/asc
                .desc()//降序
                .listPage(firstResult, pageSize);
    }

    @Override
    public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) {
        return historyService
                .createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
    }

    @Override
    public List<HistoricActivityInstance> selectHistoryTaskList(String instanceId) {
        return historyService
                .createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId)
                .activityType("userTask")//去掉网关，只查用户节点
                .finished()//只查完成任务
                .orderByHistoricActivityInstanceStartTime()
                .desc()
                .list();
    }

    @Override
    public String getTaskComment(String taskId) {
        List<Comment> taskComments = taskService.getTaskComments(taskId);//可以不传comment
        if (taskComments != null && taskComments.size() > 0) {
            return taskComments.get(0).getFullMessage();
        } else {
            return "";
        }
    }
}
